﻿using Entity;
using Essensoft.Paylink.WeChatPay;
using Essensoft.Paylink.WeChatPay.V3;
using Essensoft.Paylink.WeChatPay.V3.Domain;
using Essensoft.Paylink.WeChatPay.V3.Request;
using Furion.EventBus;
using Furion.FriendlyException;
using Logics;
using Microsoft.Extensions.Options;
using static Aliyun.OSS.Model.LiveChannelStat;

namespace Services;

/// <summary>
/// 支付接口
/// </summary>
[Authorize, ApiDescriptionSettings("支付")]
public class PayServices : BaseServices
{
    private readonly ISqlSugarClient db;

    private readonly IWeChatPayClient wechat;

    private readonly IOptions<WeChatPayOptions> options;
    private readonly Glod glodLogic;
    private readonly IEventPublisher pub;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="db"></param>
    /// <param name="wechat"></param>
    /// <param name="options"></param>
    /// <param name="glodLogic"></param>
    /// <param name="pub"></param>
    public PayServices(ISqlSugarClient db,
        IWeChatPayClient wechat, IOptions<WeChatPayOptions> options, Glod glodLogic, IEventPublisher pub)
    {
        this.db = db;
        this.wechat = wechat;
        this.options = options;
        this.glodLogic = glodLogic;
        this.pub = pub;
    }

    private async Task<Entity.Order> GetOrder(string orderNo)
    {
        var order = await db.Queryable<Entity.Order>()

            .FirstAsync(x => x.OrderNo == orderNo);

        return order;
    }

    private async Task<string> GetOpenId()
    {
        var openId = await db.Queryable<Entity.Client>().Where(x => x.Id == USERID).Select(x => x.OpenId).FirstAsync();

        return openId;
    }

    /// <summary>
    /// 微信支付
    /// </summary>
    /// <param name="orderNo"></param>
    /// <returns></returns>
    public async Task<object> Wechat(string orderNo)
    {
        var order = await GetOrder(orderNo);

        int price = (int)(order.PayPrice * 100);

        string notifyUrl = App.Configuration.GetSection("WeChatPay:nofity").Value ?? throw Oops.Oh("支付失败,notify错误");

        string openId = await GetOpenId();

        var model = new WeChatPayTransactionsJsApiBodyModel
        {
            AppId = options.Value.AppId,

            MchId = options.Value.MchId,

            Amount = new Amount
            {
                Total = price,

                Currency = "CNY"
            },
            Description = "收钱鸭线上收款",

            NotifyUrl = notifyUrl,

            OutTradeNo = orderNo,

            Payer = new PayerInfo { OpenId = openId }
        };

        var request = new WeChatPayTransactionsJsApiRequest();

        request.SetBodyModel(model);

        var response = await wechat.ExecuteAsync(request, options.Value);

        if (!response.IsError)
        {
            var req = new WeChatPayMiniProgramSdkRequest
            {
                Package = "prepay_id=" + response.PrepayId
            };

            var parameter = await wechat.ExecuteAsync(req, options.Value);

            return Ok(parameter);
        }

        return No(response.Body);
    }

    /// <summary>
    /// 金币支付
    /// </summary>
    /// <param name="orderNo"></param>
    /// <returns></returns>
    public async Task<object> Glod(string orderNo)
    {
        var order = await GetOrder(orderNo);

        if (order.OrderType != OrderType.拼团返利) return No("金币仅支持拼团订单");

        if (order.PayStatus != PayStatus.未支付) return No("订单已支付/已取消");
        
        bool state = await glodLogic.Deduct(order.UserId, order.StoreId, order.PayPrice, "金币支付排队");

        if (!state) return No("支付失败");

        await pub.PublishAsync("OrderComplete", new Events.Dto.OrderComplete 
        {
            OrderNo = order.OrderNo ?? "",

            ThreeOrderNo = order.OrderNo ?? "",

            PayType = PayType.金币,
        });

        return Ok("支付成功");
    }
}

